[system-updater] Configure public keys from assembly Added a dev key generated by `openssl genpkey -algorithm ed25519 -out manifest_dev_key.pem` The public dev key is included in eng build by default unless overridden in product config. Bug: 441769485 Change-Id: Ia8025c7e6af24bcd81a5118707ccae3394f5550c Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1387005 Fuchsia-Auto-Submit: Sen Jiang <senj@google.com> Commit-Queue: Sen Jiang <senj@google.com> Reviewed-by: Ben Keller <galbanum@google.com> Reviewed-by: Aaron Wood <aaronwood@google.com> Reviewed-by: Aidan Wolter <awolter@google.com> 
diff --git a/src/lib/assembly/config_schema/src/platform_settings/swd_config.rs b/src/lib/assembly/config_schema/src/platform_settings/swd_config.rs index 388abf4..dcd52b4 100644 --- a/src/lib/assembly/config_schema/src/platform_settings/swd_config.rs +++ b/src/lib/assembly/config_schema/src/platform_settings/swd_config.rs 
@@ -34,6 +34,11 @@    #[serde(skip_serializing_if = "crate::common::is_default")]  pub enable_upgradable_packages: bool, + + /// The public keys used to verify ota manifest in packageless updates. + /// Each key must be 32 bytes and encoded as a 64 bytes hex string. + #[serde(skip_serializing_if = "Vec::is_empty")] + pub ota_manifest_public_keys: Vec<String>,  }    /// The SWD Policies are laid out in 
diff --git a/src/lib/assembly/platform_configuration/src/subsystems/swd.rs b/src/lib/assembly/platform_configuration/src/subsystems/swd.rs index c2973a7..e671212 100644 --- a/src/lib/assembly/platform_configuration/src/subsystems/swd.rs +++ b/src/lib/assembly/platform_configuration/src/subsystems/swd.rs 
@@ -4,7 +4,7 @@    use crate::subsystems::prelude::*;  use anyhow::{Context, Result, anyhow, bail}; -use assembly_config_capabilities::{Config, ConfigValueType}; +use assembly_config_capabilities::{Config, ConfigNestedValueType, ConfigValueType};  use assembly_config_schema::platform_settings::swd_config::{  OtaConfigs, PolicyConfig, PolicyLabels, SwdConfig, UpdateChecker, VerificationFailureAction,  }; @@ -12,14 +12,13 @@  use camino::Utf8PathBuf;  use std::fs::File;   -#[allow(dead_code)] -const FUZZ_PERCENTAGE_RANGE: u32 = 25; -#[allow(dead_code)] -const RETRY_DELAY_SECONDS: u32 = 300; +// openssl pkey -in src/sys/pkg/bin/system-updater/keys/manifest_dev_key.pem -pubout -outform DER | tail -c 32 | xxd -p -c 32 +const OTA_MANIFEST_DEV_PUBLIC_KEY: &str = + "b1d9c9414b0a97a225da46ce6ae05753fa69cf722da706132ced72ccf48213e9"; +const OTA_MANIFEST_PUBLIC_KEY_HEX_LEN: usize = 64;    /// SWD Configuration implementation detail which clarifies different subsystem behavior, derived  /// from the PolicyLabels -#[allow(dead_code)]  #[derive(Debug)]  pub struct PolicyLabelDetails {  enable_dynamic_configuration: bool, @@ -50,19 +49,6 @@  }  }   -impl DefaultByBuildType for SwdConfig { - fn default_by_build_type(build_type: &BuildType) -> Self { - SwdConfig { - policy: Some(PolicyLabels::default_by_build_type(build_type)), - update_checker: Some(UpdateChecker::default_by_build_type(build_type)), - on_verification_failure: VerificationFailureAction::default(), - tuf_config_paths: vec![], - include_configurator: false, - enable_upgradable_packages: false, - } - } -} -  pub(crate) struct SwdSubsystemConfig;  impl DefineSubsystemConfiguration<SwdConfig> for SwdSubsystemConfig {  /// Configures the SWD system. If a specific field is not specified, a @@ -128,6 +114,38 @@  Config::new(ConfigValueType::Bool, subsystem_config.enable_upgradable_packages.into()),  )?;   + let manifest_public_keys = if subsystem_config.ota_manifest_public_keys.is_empty() + && context.build_type == &BuildType::Eng + { + // Include a default dev key in eng builds. + [OTA_MANIFEST_DEV_PUBLIC_KEY].into() + } else { + for key in &subsystem_config.ota_manifest_public_keys { + if key.len() != OTA_MANIFEST_PUBLIC_KEY_HEX_LEN { + bail!( + "OTA manifest public key must be {} hex characters, but {:?} has {}", + OTA_MANIFEST_PUBLIC_KEY_HEX_LEN, + key, + key.len(), + ); + } + } + (&*subsystem_config.ota_manifest_public_keys).into() + }; + + builder.set_config_capability( + "fuchsia.system-updater.ManifestPublicKeys", + Config::new( + ConfigValueType::Vector { + nested_type: ConfigNestedValueType::String { + max_size: OTA_MANIFEST_PUBLIC_KEY_HEX_LEN as u32, + }, + max_count: 10, + }, + manifest_public_keys, + ), + )?; +  Ok(())  }  } 
diff --git a/src/recovery/system/meta/core_shards/system_recovery_android.core_shard.cml b/src/recovery/system/meta/core_shards/system_recovery_android.core_shard.cml index 326aee1..624965d 100644 --- a/src/recovery/system/meta/core_shards/system_recovery_android.core_shard.cml +++ b/src/recovery/system/meta/core_shards/system_recovery_android.core_shard.cml 
@@ -39,7 +39,10 @@  to: "#system_recovery",  },  { - config: [ "fuchsia.recovery.DisplayRotation" ], + config: [ + "fuchsia.recovery.DisplayRotation", + "fuchsia.system-updater.ManifestPublicKeys", + ],  from: "parent",  to: "#system_recovery",  availability: "same_as_target", 
diff --git a/src/recovery/system/meta/system_recovery_android.cml b/src/recovery/system/meta/system_recovery_android.cml index 422261d..cc34094 100644 --- a/src/recovery/system/meta/system_recovery_android.cml +++ b/src/recovery/system/meta/system_recovery_android.cml 
@@ -111,6 +111,11 @@  to: "#pkg-recovery",  dependency: "weak",  }, + { + config: "fuchsia.system-updater.ManifestPublicKeys", + from: "parent", + to: "#pkg-recovery", + },  ],  expose: [  { 
diff --git a/src/security/tests/pkg_test/tests/access_ota_blob_as_executable/meta/access_ota_blob_as_executable.cml b/src/security/tests/pkg_test/tests/access_ota_blob_as_executable/meta/access_ota_blob_as_executable.cml index 4f2f969..df9af8a 100644 --- a/src/security/tests/pkg_test/tests/access_ota_blob_as_executable/meta/access_ota_blob_as_executable.cml +++ b/src/security/tests/pkg_test/tests/access_ota_blob_as_executable/meta/access_ota_blob_as_executable.cml 
@@ -105,6 +105,16 @@  backing_dir: "tmp",  storage_id: "static_instance_id_or_moniker",  }, + { + config: "fuchsia.system-updater.ManifestPublicKeys", + type: "vector", + max_count: 10, + element: { + type: "string", + max_size: 64, + }, + value: [], + },  ],  use: [  // Control storage capabilities of this realm. See @@ -136,6 +146,7 @@  {  protocol: "fuchsia.update.installer.Installer",  from: "#system-updater", + dependency: "weak",  },  {  protocol: [ @@ -208,6 +219,11 @@  availability: "optional",  },  { + config: "fuchsia.system-updater.ManifestPublicKeys", + from: "self", + to: "#system-updater", + }, + {  directory: "blob-exec",  from: "#fshost",  as: "blob", 
diff --git a/src/security/tests/pkg_test/tests/bad_signature_update/meta/bad_signature_update.cml b/src/security/tests/pkg_test/tests/bad_signature_update/meta/bad_signature_update.cml index d73928d..ae50500 100644 --- a/src/security/tests/pkg_test/tests/bad_signature_update/meta/bad_signature_update.cml +++ b/src/security/tests/pkg_test/tests/bad_signature_update/meta/bad_signature_update.cml 
@@ -101,6 +101,16 @@  backing_dir: "tmp",  storage_id: "static_instance_id_or_moniker",  }, + { + config: "fuchsia.system-updater.ManifestPublicKeys", + type: "vector", + max_count: 10, + element: { + type: "string", + max_size: 64, + }, + value: [], + },  ],  use: [  // Control storage capabilities of this realm. See @@ -132,6 +142,7 @@  {  protocol: "fuchsia.update.installer.Installer",  from: "#system-updater", + dependency: "weak",  },  ],  offer: [ @@ -198,6 +209,11 @@  availability: "optional",  },  { + config: "fuchsia.system-updater.ManifestPublicKeys", + from: "self", + to: "#system-updater", + }, + {  directory: "blob-exec",  from: "#fshost",  as: "blob", 
diff --git a/src/sys/core/meta/core.root_shard.cml b/src/sys/core/meta/core.root_shard.cml index 25e1b89..30fdfee 100644 --- a/src/sys/core/meta/core.root_shard.cml +++ b/src/sys/core/meta/core.root_shard.cml 
@@ -63,6 +63,7 @@  "fuchsia.session.window.Collection",  "fuchsia.session.window.InitialElementUrl",  "fuchsia.session.window.InitialViewIdAnnotation", + "fuchsia.system-updater.ManifestPublicKeys",  "fuchsia.time.config.HasWakeAlarms",  "fuchsia.time.config.WritableUTCTime",  "fuchsia.ui.AttachA11yView", 
diff --git a/src/sys/pkg/bin/system-updater/keys/manifest_dev_key.pem b/src/sys/pkg/bin/system-updater/keys/manifest_dev_key.pem new file mode 100644 index 0000000..da9b4ff --- /dev/null +++ b/src/sys/pkg/bin/system-updater/keys/manifest_dev_key.pem 
@@ -0,0 +1,3 @@ +-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VwBCIEIHF6l/uIsoxSPqvEgnyczWwdNIB5w9Tao8Ijp6Cv9OLT +-----END PRIVATE KEY----- 
diff --git a/src/sys/pkg/bin/system-updater/meta/system-updater-common.shard.cml b/src/sys/pkg/bin/system-updater/meta/system-updater-common.shard.cml index 78e4aa7..e94f670 100644 --- a/src/sys/pkg/bin/system-updater/meta/system-updater-common.shard.cml +++ b/src/sys/pkg/bin/system-updater/meta/system-updater-common.shard.cml 
@@ -44,6 +44,16 @@  rights: [ "r*" ],  path: "/blob",  }, + { + config: "fuchsia.system-updater.ManifestPublicKeys", + key: "manifest_public_keys", + type: "vector", + max_count: 10, + element: { + type: "string", + max_size: 64, // hex encoded 32 bytes key + }, + },  ],  expose: [  { 
diff --git a/src/sys/pkg/bin/system-updater/meta/system_updater.core_shard.cml b/src/sys/pkg/bin/system-updater/meta/system_updater.core_shard.cml index c660d79..8ad4f56 100644 --- a/src/sys/pkg/bin/system-updater/meta/system_updater.core_shard.cml +++ b/src/sys/pkg/bin/system-updater/meta/system_updater.core_shard.cml 
@@ -54,5 +54,10 @@  from: "self",  to: "#system-update",  }, + { + config: "fuchsia.system-updater.ManifestPublicKeys", + from: "parent", + to: "#system-update", + },  ],  } 
diff --git a/src/sys/pkg/bin/system-updater/meta/system_updater.system_update_shard.cml b/src/sys/pkg/bin/system-updater/meta/system_updater.system_update_shard.cml index 476d864..4f4a6280 100644 --- a/src/sys/pkg/bin/system-updater/meta/system_updater.system_update_shard.cml +++ b/src/sys/pkg/bin/system-updater/meta/system_updater.system_update_shard.cml 
@@ -63,6 +63,11 @@  from: "parent",  to: "#system-updater",  }, + { + config: "fuchsia.system-updater.ManifestPublicKeys", + from: "parent", + to: "#system-updater", + },  ],  expose: [  { 
diff --git a/src/sys/pkg/lib/isolated-swd/BUILD.gn b/src/sys/pkg/lib/isolated-swd/BUILD.gn index 4d7b18a..1e47ef3 100644 --- a/src/sys/pkg/lib/isolated-swd/BUILD.gn +++ b/src/sys/pkg/lib/isolated-swd/BUILD.gn 
@@ -37,6 +37,7 @@  "//src/lib/fuchsia-component-test",  "//src/lib/fuchsia-url",  "//src/storage/fxfs/fidl/fuchsia.fxfs:fuchsia.fxfs_rust", + "//src/sys/lib/cm_rust",  "//src/sys/lib/fidl-fuchsia-pkg-ext",  "//src/sys/pkg/lib/fuchsia-merkle",  "//src/sys/pkg/lib/fuchsia-pkg-testing", 
diff --git a/src/sys/pkg/lib/isolated-swd/src/updater.rs b/src/sys/pkg/lib/isolated-swd/src/updater.rs index 6125a9b..6fe37b2 100644 --- a/src/sys/pkg/lib/isolated-swd/src/updater.rs +++ b/src/sys/pkg/lib/isolated-swd/src/updater.rs 
@@ -381,6 +381,24 @@  )  .await  .unwrap(); + realm_builder + .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl { + name: "fuchsia.system-updater.ManifestPublicKeys".parse().unwrap(), + value: Vec::<String>::new().into(), + })) + .await + .unwrap(); + realm_builder + .add_route( + Route::new() + .capability(Capability::configuration( + "fuchsia.system-updater.ManifestPublicKeys", + )) + .from(Ref::self_()) + .to(&system_updater), + ) + .await + .unwrap();    // Make sure the component under test can log.  realm_builder 
diff --git a/src/sys/pkg/meta/pkg-recovery.cml b/src/sys/pkg/meta/pkg-recovery.cml index c13cd02..c564026 100644 --- a/src/sys/pkg/meta/pkg-recovery.cml +++ b/src/sys/pkg/meta/pkg-recovery.cml 
@@ -87,6 +87,11 @@  to: "#pkg-cache",  },  { + config: "fuchsia.system-updater.ManifestPublicKeys", + from: "parent", + to: "#system-updater", + }, + {  // Needed for passing repository configs to pkg-resolver  directory: "config-data",  from: "parent", 
diff --git a/src/sys/pkg/tests/isolated-ota/BUILD.gn b/src/sys/pkg/tests/isolated-ota/BUILD.gn index 92789cb..25dac60 100644 --- a/src/sys/pkg/tests/isolated-ota/BUILD.gn +++ b/src/sys/pkg/tests/isolated-ota/BUILD.gn 
@@ -20,6 +20,7 @@  "//src/lib/fuchsia-sync",  "//src/lib/fuchsia-url",  "//src/storage/lib/vfs/rust:vfs", + "//src/sys/lib/cm_rust",  "//src/sys/lib/fidl-fuchsia-pkg-ext",  "//src/sys/pkg/lib/fuchsia-hash",  "//src/sys/pkg/lib/fuchsia-pkg-testing", 
diff --git a/src/sys/pkg/tests/isolated-ota/src/lib.rs b/src/sys/pkg/tests/isolated-ota/src/lib.rs index 6704fb0..661cef4 100644 --- a/src/sys/pkg/tests/isolated-ota/src/lib.rs +++ b/src/sys/pkg/tests/isolated-ota/src/lib.rs 
@@ -297,6 +297,25 @@  .await  .unwrap();   + realm_builder + .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl { + name: "fuchsia.system-updater.ManifestPublicKeys".parse().unwrap(), + value: Vec::<String>::new().into(), + })) + .await + .unwrap(); + realm_builder + .add_route( + Route::new() + .capability(Capability::configuration( + "fuchsia.system-updater.ManifestPublicKeys", + )) + .from(Ref::self_()) + .to(&pkg_component), + ) + .await + .unwrap(); +  let channel_clone = params.channel.clone();    let realm_instance = realm_builder.build().await.unwrap(); 
diff --git a/src/sys/pkg/tests/omaha-client/src/lib.rs b/src/sys/pkg/tests/omaha-client/src/lib.rs index 50a8074..1c9bcf8 100644 --- a/src/sys/pkg/tests/omaha-client/src/lib.rs +++ b/src/sys/pkg/tests/omaha-client/src/lib.rs 
@@ -594,6 +594,24 @@  )  .await  .unwrap(); + builder + .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl { + name: "fuchsia.system-updater.ManifestPublicKeys".parse().unwrap(), + value: Vec::<String>::new().into(), + })) + .await + .unwrap(); + builder + .add_route( + Route::new() + .capability(Capability::configuration( + "fuchsia.system-updater.ManifestPublicKeys", + )) + .from(Ref::self_()) + .to(&system_updater), + ) + .await + .unwrap();  } else {  builder  .add_route( 
diff --git a/src/sys/pkg/tests/system-updater/BUILD.gn b/src/sys/pkg/tests/system-updater/BUILD.gn index b43fe4c..26947f0 100644 --- a/src/sys/pkg/tests/system-updater/BUILD.gn +++ b/src/sys/pkg/tests/system-updater/BUILD.gn 
@@ -28,6 +28,7 @@  "//src/lib/fuchsia-sync",  "//src/lib/fuchsia-url",  "//src/storage/fxfs/fidl/fuchsia.fxfs:fuchsia.fxfs_rust", + "//src/sys/lib/cm_rust",  "//src/sys/lib/fidl-fuchsia-pkg-ext",  "//src/sys/pkg/fidl/fuchsia.update.installer:fuchsia.update.installer_rust",  "//src/sys/pkg/lib/fidl-fuchsia-update-installer-ext", 
diff --git a/src/sys/pkg/tests/system-updater/src/lib.rs b/src/sys/pkg/tests/system-updater/src/lib.rs index cff4427..1d52fd5 100644 --- a/src/sys/pkg/tests/system-updater/src/lib.rs +++ b/src/sys/pkg/tests/system-updater/src/lib.rs 
@@ -586,11 +586,22 @@  .set_config_value(&system_updater, "allow_packageless_update", true.into())  .await  .unwrap(); +  builder - .set_config_value( - &system_updater, - "manifest_public_keys", - vec![MANIFEST_PUBLIC_KEY].into(), + .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl { + name: "fuchsia.system-updater.ManifestPublicKeys".parse().unwrap(), + value: vec![MANIFEST_PUBLIC_KEY].into(), + })) + .await + .unwrap(); + builder + .add_route( + Route::new() + .capability(Capability::configuration( + "fuchsia.system-updater.ManifestPublicKeys", + )) + .from(Ref::self_()) + .to(&system_updater),  )  .await  .unwrap();